package com.aneliya.server;

import java.io.IOException;
import java.net.SocketTimeoutException;

import com.aneliya.framework.mvc.Facade;
import com.aneliya.framework.mvc.controller.MVCEvent;
import com.aneliya.io.IStreamStrategy;
import com.aneliya.model.ErrorType;
import com.aneliya.model.Message;
import com.aneliya.proxy.ServerProxy;
import com.aneliya.proxy.UserProxy;

public class ServerListener extends Thread {
	
	private IStreamStrategy streamStrategy;
	public void setStreamStrategy(IStreamStrategy streamStrategy) {
		this.streamStrategy = streamStrategy;
	}
	
	public void run() {
		try {
			while (!isInterrupted()) {
				try {
					Message message = streamStrategy.readMessage();
					if (message == null) {
						break;
					}
					handleMessage(message);
				} catch (SocketTimeoutException ex) {
					// TODO handle socket timeout exception
				}
			}
		} catch (IOException ex) {
			// Communication problem
		}
	}

	
	public void handleMessage(Message message) {
		switch (message.getMessageType()) {
		case LOGIN:
			handleLoginMessage(message);
			break;
		case LOGOUT:
			handleLogoutMessage(message);
			break;
		case TEXT:
			handleTextMessage(message);
			break;
		case ERROR:
			handleErrorMessage(message);

		default:
			System.out.println("received message of type: " + message.getMessageType());
			break;
		}
	}

	private void handleLoginMessage(Message message) {
		try {
			MVCEvent event = new MVCEvent(this, ServerProxy.LOGIN_RECEIVED_EVENT, message.getUsername());
			Facade.getInstance().dispatchMVCEvent(event);
		} catch (InstantiationException ex) {
			ex.printStackTrace();
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}
		
	private void handleLogoutMessage(Message message) {
		try {
			MVCEvent event = new MVCEvent(this, ServerProxy.LOGOUT_RECEIVED_EVENT, message.getUsername());
			Facade.getInstance().dispatchMVCEvent(event);
		} catch (InstantiationException ex) {
			ex.printStackTrace();
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}

	private void handleTextMessage(Message message) {
		try {
			MVCEvent event = new MVCEvent(this, ServerProxy.MESSAGE_RECEIVED_EVENT, message);
			Facade.getInstance().dispatchMVCEvent(event);
		} catch (InstantiationException ex) {
			ex.printStackTrace();
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}
	
	private void handleErrorMessage(Message message) {
		ErrorType error = (ErrorType) message.getMessage();
		switch (error) {
		case LOGIN_FAILED:
			handleLoginFailedError();
			break;
		case REGISTER_FAILED:
			handleRegisterFailedError();
			break;

		default:
			System.out.println("received error of type: " + error);
			break;
		}
	}

	private void handleLoginFailedError() {
		try {
			Facade.getInstance().dispatchMVCEvent(new MVCEvent(this, UserProxy.LOGIN_FAILED_EVENT, null));
		} catch (InstantiationException ex) {
			ex.printStackTrace();
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}

	private void handleRegisterFailedError() {
		try {
			Facade.getInstance().dispatchMVCEvent(new MVCEvent(this, UserProxy.REGISTRATION_FAILED_EVENT, null));
		} catch (InstantiationException ex) {
			ex.printStackTrace();
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}
	
}
